﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.IO;
using System.Windows.Media.Effects;
using System.Windows.Media.Animation;
using System.Threading;
using System.Windows.Threading;
using WPFMultitouchDemo.Adorners;
using WPFMultitouchDemo.UserControls;

namespace WPFMultitouchDemo
{
    /// <summary>
    /// Interaction logic for InteractiveShapesWindow.xaml
    /// </summary>
    public partial class InteractiveShapesWindow : Window
    {
        private bool _isDragging = false;
        private Point _startPoint;
        private Point _selectedElementOrigin;
        private UIElement _selectedElement;
        private Point _lastPosition;
        private Vector _mouseDirection;
        private double _mouseVelocity;
        private Timer _timer;

        public InteractiveShapesWindow()
        {
            InitializeComponent();
            _timer = new Timer(new TimerCallback(timer_Tick));
            _timer.Change(0, 50);
        }

        #region Control Events

        private void leftMouseDown(object sender, MouseButtonEventArgs e)
        {
            // don't drag the canvas
            if (e.Source == canvas1)
                return;

            if (!_isDragging)
            {
                DoubleAnimation fadeIn = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(.25)), FillBehavior.HoldEnd);
                DoubleAnimation fadeOut = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(.25)), FillBehavior.HoldEnd);

                _startPoint = e.GetPosition(canvas1);
                _selectedElement = e.Source as UIElement;

                ClearAnimation();

                canvas1.Children.Remove(_selectedElement);
                canvas1.Children.Add(_selectedElement);

                canvas1.CaptureMouse();

                _isDragging = true;

                _selectedElementOrigin = new Point();
                _selectedElementOrigin.X = Canvas.GetLeft(_selectedElement);
                _selectedElementOrigin.Y = Canvas.GetTop(_selectedElement);

            }

            e.Handled = true;
        }

        private void leftMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (canvas1.IsMouseCaptured)
            {
                _isDragging = false;
                canvas1.ReleaseMouseCapture();
                e.Handled = true;
                ContinueMovementAfterRelease(_selectedElement);

            }
        }

        private void mouseMove(object sender, MouseEventArgs e)
        {
            if (canvas1.IsMouseCaptured)
            {
                if (_isDragging)
                {
                    Point curr = e.GetPosition(canvas1);

                    double newLeft = (curr.X - _startPoint.X) + _selectedElementOrigin.X;
                    double newTop = (curr.Y - _startPoint.Y) + _selectedElementOrigin.Y;
                    Canvas.SetLeft(_selectedElement, newLeft);
                    Canvas.SetTop(_selectedElement, newTop);
                }
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            _timer.Change(Timeout.Infinite, Timeout.Infinite);


            this.Close();
        }

        private void createShapes_Click(object sender, RoutedEventArgs e)
        {
            GenerateRandomShapes();
        }

        private void loadMedia_click(object sender, RoutedEventArgs e)
        {
            
            canvas1.Children.Clear();

            DropShadowEffect dse = new DropShadowEffect();
            Random rand = new Random();
            string[] files = Directory.GetFiles("media");
            foreach (string f in files)
            {
                PhotoImage img = new PhotoImage();
                BitmapImage bs = new BitmapImage();
                bs.BeginInit();
                bs.DecodePixelHeight = 300;
                bs.CacheOption = BitmapCacheOption.OnLoad;
                bs.UriSource = new Uri(f, UriKind.Relative);
                bs.EndInit();
                
                img.Image.Source = bs;
                img.Height = 300;
                img.RenderTransformOrigin = new Point(.5, .5);
                
                //if (RenderCapability.Tier == 0x20000)
                //{
                //    img.Effect = dse;
                //}

                TransformGroup transforms = new TransformGroup();
                RotateTransform imgRotate = new RotateTransform(rand.Next(-20,20));
                ScaleTransform imgScale = new ScaleTransform(1, 1);
                transforms.Children.Add(imgRotate);
                transforms.Children.Add(imgScale);
                                
                img.RenderTransform = transforms;

                Canvas.SetTop(img, rand.Next(50,(int)canvas1.ActualHeight - 250));
                Canvas.SetLeft(img, rand.Next(50,(int)canvas1.ActualWidth - 300));

                FloatInElement(rand, img);


                canvas1.Children.Add(img);
            }
        }

  
        #endregion

        private void timer_Tick(object state)
        {
            Dispatcher.Invoke(DispatcherPriority.Normal,
                (Action)delegate()
                {
                    Point current = Mouse.GetPosition(this);
                    _mouseDirection = (current - _lastPosition);
                    // velocity is distance / time, so the length of the last move / 50 milliseconds
                    _mouseVelocity = _mouseDirection.Length / .05;
                    mouseVelocity.Text = _mouseVelocity.ToString();
                    _lastPosition = current;
                });
                
        }


        private void ClearAnimation()
        {
            double top, left;
            top = Canvas.GetTop(_selectedElement);
            left = Canvas.GetLeft(_selectedElement);

            _selectedElement.BeginAnimation(Canvas.TopProperty, null);
            _selectedElement.BeginAnimation(Canvas.LeftProperty, null);
            Canvas.SetTop(_selectedElement, top);
            Canvas.SetLeft(_selectedElement, left);
        }


        private void GenerateRandomShapes()
        {
            canvas1.Children.Clear();
            Random rand = new Random();
            for (int i = 0; i < 20; i++)
            {
                Shape s = null;
                switch (rand.Next(0,100) % 3)
                { 
                    case 0:
                        s = new Rectangle();
                        break;
                    case 1:
                        s = new Ellipse();
                        break;
                    case 2:
                        s = new Polygon();
                        int startx = rand.Next(1,50);
                        int starty = rand.Next(150, 200);
                        System.Windows.Point Point1 = new System.Windows.Point(rand.Next(0,75), rand.Next(0,75));
                        System.Windows.Point Point2 = new System.Windows.Point(rand.Next(100,300), rand.Next(100,300));
                        System.Windows.Point Point3 = new System.Windows.Point(rand.Next(100,200), rand.Next(100,200));
                        ((Polygon)s).Points.Add(Point1);
                        ((Polygon)s).Points.Add(Point2);
                        ((Polygon)s).Points.Add(Point3);

                        break;
                }
                s.Height = rand.Next(75,300);
                s.Width = rand.Next(75,300);
                s.Stroke = new SolidColorBrush(Colors.Black);
                s.Fill = GetRandomColor(rand.Next());
                Canvas.SetTop(s, (double)rand.Next(0,(int)canvas1.ActualHeight -20));
                Canvas.SetLeft(s, (double)rand.Next(0,(int)canvas1.ActualWidth -20));
                s.Opacity = 0;
                FloatInElement(rand, s);
                canvas1.Children.Add(s);
            }
        }

        private SolidColorBrush GetRandomColor(int seed)
        { 
            Random rand = new Random(seed);
            
            //string [] colors = Enum.GetNames(typeof(Colors));
            //return (SolidColorBrush)Enum.Parse(typeof(Colors), colors[rand.Next(0, colors.Length - 1)]);
            int r = rand.Next(0,255);
            int g = rand.Next(0,255);
            int b = rand.Next(0,255);
            
            return new SolidColorBrush(Color.FromRgb((byte)r,(byte)g,(byte)b));
        }

        private void FloatInElement(Random rand, UIElement elem)
        {
            elem.Opacity = 0;

            DoubleAnimation opacity = new DoubleAnimation(1, new Duration(TimeSpan.FromSeconds(.5)));
            double yRange = Canvas.GetTop(elem) + rand.Next(-50, 50);
            double xRange = Canvas.GetLeft(elem) + rand.Next(-50, 50);
            DoubleAnimation floatY = new DoubleAnimation(yRange, new Duration(TimeSpan.FromSeconds(1)));
            DoubleAnimation floatX = new DoubleAnimation(xRange, new Duration(TimeSpan.FromSeconds(1)));
            floatY.DecelerationRatio = .5;
            floatX.DecelerationRatio = .5;


            elem.BeginAnimation(Canvas.TopProperty, floatY);
            elem.BeginAnimation(Canvas.LeftProperty, floatX);
            elem.BeginAnimation(Image.OpacityProperty, opacity);
        }

        private void ContinueMovementAfterRelease(UIElement elem)
        {
            double xTo = _mouseDirection.X + Canvas.GetLeft(_selectedElement);
            double yTo = _mouseDirection.Y + Canvas.GetTop(_selectedElement);


           double moveTime = .75;
            Duration dur = new Duration(TimeSpan.FromSeconds(moveTime));

            DoubleAnimation xMovement = new DoubleAnimation(xTo, dur);
            xMovement.DecelerationRatio = .5;
            DoubleAnimation yMovement = new DoubleAnimation(yTo, dur);
            yMovement.DecelerationRatio = .5;

            _selectedElement.BeginAnimation(Canvas.LeftProperty, xMovement);
            _selectedElement.BeginAnimation(Canvas.TopProperty, yMovement);
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            _timer.Change(Timeout.Infinite, Timeout.Infinite);

        }
   }
}
